#include "secuencial_indexado.h"

#define DENS_MIN				0.3 /** REVISAR SI LA DENSIDAD ES LA ADECUADA */

SecuencialIndexado::SecuencialIndexado(std::string& nombre, unsigned int tam_bloque, unsigned int tam_bloque_indice):ArchivoDatos(nombre, tam_bloque, tam_bloque_indice){
	std::string aux = nombre +EXT_EELL;
	bloques_libres = new ArchBloquesLibres(aux,TAM_EELL);
	indice_secundario = NULL;
	std::string nombre_ind_primario = nombre + ".tree";
	indice_primario = new IndiceArbol(nombre_ind_primario,tam_bloque_indice,(TiposArchivo) INDICE_B_MAS);
}

SecuencialIndexado::~SecuencialIndexado(){
	//Si el archivo esta abierto, lo cerramos
	this->cerrar();
	//deleteo todos sus integrantes
	delete(bloques_libres);	
	delete(indice_primario);
	if(this->indice_secundario != NULL)
			delete(indice_secundario);
}
	
void SecuencialIndexado::abrir() throw(ExcepAbriendoArch){
	(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Abriendo el archivo "+ this->get_nombre());
	//Si el archivo de datos esta abierto, arrojo excep
	if (this->fd != -1)
		throw ExcepAbriendoArch("Error - El archivo: " + this->get_nombre() + " ya estaba abierto.");
	else {
		std::string dest = "./DATA/" + this->get_nombre();
		this->fd = ManejadorArchivos::get_instance()->abrir_archivo(dest);
		if ( this->fd == -1)
			throw ExcepAbriendoArch (ManejadorErrores::get_msg_error(errno) + " Archivo: " + this->get_nombre());
		bloques_libres->abrir(); //arroja una excepcion en caso de no poder abrirlo
		indice_primario->abrir();
		if(this->indice_secundario != NULL)
			indice_secundario->abrir();
		bloques_libres->agregar_observador(Buffer::get_instance());
		this-> cant_bloques = get_cant_bloques_header();
	}	
}
				
void SecuencialIndexado::crear(std::string formato) throw(ExcepCreandoArch, ExcepSintaxisParser, ExcepBloqueTam){
	(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Creando el archivo "+ this->get_nombre());
	if(this->get_tam_bloque() < get_primera_pos())
		throw ExcepBloqueTam("Error - No se pudo crear el archivo. El tamaño del bloque es muy pequeno para la cabecera");
	else{
		try{
			Archivo::cargar_registro_base(formato);
			TipoStruct * reg = get_registro_base();
			if(reg->get_tamanio() == 0){
				throw ExcepSintaxisParser("Error - No se ingreso formato para el archivo");
			}
			if((*reg)[0].get_codigo_tipo() != INT)
				throw ExcepSintaxisParser("Error - El campo 0 del archivo 'secIndexado' debe ser numerico. ");	
			std::string dest = "./DATA/" + this->get_nombre();
			this->fd = ManejadorArchivos::get_instance()->crear_archivo(dest);
			if ( this->fd == -1 )
				throw ExcepCreandoArch (ManejadorErrores::get_msg_error(errno) + " Archivo: " + this->get_nombre());
			bloques_libres->crear(); //arroja una excepcion en caso de no poder crearlo.
			bloques_libres->agregar_observador(Buffer::get_instance());
			indice_primario->crear();
			//Crea el header, y le guarda el formato
			dest = this->get_nombre() + ".head";
			Header head(dest);
			head.crear();
			head.guardar(formato, this);
			head.cerrar();
			
			//Creo el bloque 0 de header y lo guardo
			Bloque* bloque_header = new Bloque(0, this->get_tam_bloque());
			Buffer::get_instance()->guardar_bloque(*this, bloque_header);
			delete (bloque_header);
			//Asigno que la cant de bloques es 1
			this->set_cant_bloques_header(1);
			this->cant_bloques = 1;
		}
		catch(ExcepSintaxisParser &e){
			throw e; //para hacerlo explicito
		}
	}	
}
		
void SecuencialIndexado::cerrar() {
	(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Cerrando el archivo "+ this->get_nombre());
	if(fd != -1){
		set_cant_bloques_header(this->cant_bloques);
		this->set_cambio();
		this->avisar_observadores(NULL);
		ManejadorArchivos::get_instance()->cerrar_archivo(this->fd);
		bloques_libres->cerrar();
		indice_primario->cerrar();
		if(this->indice_secundario != NULL)
			indice_secundario->cerrar();
		this->fd = -1;
	}
}
		
		
Bloque* SecuencialIndexado::crear_bloque() {
	Bloque* bloque_nuevo;
	//pido al archivo de bloques libres uno disponible, me devuelve el num de bloque
	int b_libre = bloques_libres->get_bloque_libre();
	(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se pide un nuevo bloque al arch de bbll." );
	if(b_libre != (-1))
		//hay un bloque disponbible lo Obtengo desde el buffer
		bloque_nuevo = Buffer::get_instance()->get_bloque(*this, b_libre);
	else{
		(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> No hay bloque, se crea uno nuevo." );
		//Creo un bloque nuevo vacio
		bloque_nuevo = new Bloque(cant_bloques, this->get_tam_bloque());
		cant_bloques++; //Incremento la cant de bloques del arch
	}
	return bloque_nuevo;	
}	

	
void SecuencialIndexado::ingresar(TipoStruct * reg) 
								throw(ExcepArchCerrado,ExcepRegExistente, ExcepBloqueTam){
	(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se ingresa un nuevo registro." );
	if (this->fd == -1)
		throw ExcepArchCerrado("Error - El archivo : "+ this-> get_nombre() +" esta cerrado. ");
	Bloque* bloque_actual = NULL;
	if (es_unico(reg)){
		unsigned int tam = reg->get_tamanio_serializado();
		//Verifico que el registro tenga menor tamanio que el bloque
		if( tam <= this->get_tam_bloque() - this->get_primera_pos()){ 
			//consulto en el indice en que bloque deberia ubicarlo para mantener el orden
			(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se consulta en el indice primario el bloque donde poner el registro." );
			int num_bloque = ((IndiceArbol*) indice_primario)->consultar_ubicacion(&(*reg)[0]);		
			//si me da -1 quiere decir que no hay bloques que es el primer ingreso
			if (num_bloque == -1){
				bloque_actual = crear_bloque();
				num_bloque = bloque_actual->get_num_bloque();
			}
			else	
				//Obtengo el bloque desde el buffer
				bloque_actual = Buffer::get_instance()->get_bloque(*this, num_bloque);
			bool entro = poner_reg_en_bloque(bloque_actual, reg);
			if (!entro) {
				(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> El registro no entra. Se produce overflow." );
				TipoDato* clave = NULL;
				//no entro pero tiene que permanecer ordenado, partimos el bloque	
				Bloque* bloque_nuevo = NULL;
				bloque_nuevo = crear_bloque();
				num_bloque = bloque_nuevo->get_num_bloque();
				//devuelve en el nuevo la segunda mitad, para no alterar indice
				//devuelve en bloque_actual la primer mitad, e ingresa el reg donde corresponda
				(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se divide el contenido entre los 2 bloques." );
				dividir_bloque(bloque_actual,bloque_nuevo,reg);
				//actualizo el indice con la nueva entrada del bloque nuevo
				BloqueSec * nuevo = new BloqueSec(bloque_nuevo, this->get_registro_base());
				clave = nuevo->obtener_primera_clave();
				(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se actualiza el indice primario." );
				indice_primario->ingresar(clave,num_bloque);
				delete (nuevo);
				//guardo los bloques en disco con los cambios realizados
				Buffer::get_instance()->guardar_bloque(*this,bloque_nuevo);
				Buffer::get_instance()->guardar_bloque(*this,bloque_actual);
				delete (bloque_nuevo);
				delete (clave);
			} else
				(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se ingresa el registro en el bloque." );
	
			if(indice_secundario !=NULL)
				indice_secundario->ingresar(reg);
					
			delete (bloque_actual);
		}
		else
			throw ExcepBloqueTam("Error - El dato a ingresar es mas grande que el tamano del bloque de " + this->get_nombre() + ". ");
	}
	else
		throw ExcepRegExistente("Error - El registro que intenta ingresar ya existe en el archivo. ");
}

void SecuencialIndexado::actualizar_primero(TipoDato* clave, Bloque* bloque){
	BloqueSec* nuevo = new BloqueSec(bloque, this->get_registro_base());
	TipoDato* clave_nueva = nuevo->obtener_primera_clave();
	if ((clave_nueva != NULL) && !((*clave_nueva) == (*clave))) {
		unsigned int num_bloque = indice_primario->consultar(clave);
		indice_primario->quitar(clave); //le paso la vieja y despues la actual
		indice_primario->ingresar(clave_nueva, num_bloque);
	}
	delete nuevo;
	if (clave_nueva != NULL)
		delete clave_nueva;
}

void SecuencialIndexado::quitar(std::vector<ParesDatos*> &elementos, std::vector<TipoStruct*> &resultado) 
									throw(ExcepArchCerrado){
	(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se quita un registro." );
	if (this-> fd != -1){
		if( (elementos.size() != 1) || (elementos[0]->get_numero_campo() != 0) ){
			if(!quitar_indice_secundario(elementos,resultado)) {
				quitar_secuencial(elementos,resultado);
				(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se quita recorriendo secuencialmente el archivo." );
			} else
				(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se quita utilizando el indice secundario." );
		}
		else{
			(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se quita buscandolo por campo clave en indice primario." );
			TipoDato* clave = elementos[0]->get_valor();
			
			//obtengo a traves del indice el numero de bloque donde buscar el reg asociado a la clave
			int num_bloque = indice_primario->consultar(clave);
			//queda posicionado en esa posicion
			if (num_bloque != Indice::VACIO) {
				(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se encontro el bloque en el indice primario. Se busca secuencial dentro del mismo." );
				Bloque*	bloque_actual = Buffer::get_instance()->get_bloque(*this,num_bloque);
				BloqueSec bloque_sec (bloque_actual, this->get_registro_base());
				unsigned int pos;
				bool clave_encontrada;
				//lo busco dentro del bloque, se que es unico por que es consulta por campo 0			
				clave_encontrada = bloque_sec.buscar_registro(clave,pos);
				if (clave_encontrada){
					TipoStruct* reg = bloque_sec.get_registro(clave);
					sacar_reg_bloque(bloque_actual,reg,pos,reg->get_tamanio_serializado());
					resultado.push_back(reg);
					//actualizo indice secundario
					if (indice_secundario!= NULL)
						indice_secundario->quitar(reg);		
				}	
				delete(bloque_actual);
			}
		}
	}else
		throw ExcepArchCerrado("Error - El archivo : "+ this-> get_nombre() +" esta cerrado. ");					 	
}

void SecuencialIndexado::consultar(std::vector<ParesDatos*> &consultas, std::vector<TipoStruct*> &resultado)
												 throw(ExcepArchCerrado,ExcepLeerBloque){
	(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se realiza una consulta." );
	if (this-> fd != -1){
		if( (consultas.size() != 1) || (consultas[0]->get_numero_campo() != 0) ){
			if(!consultar_indice_secundario(consultas,resultado)) {
				consultar_secuencial(consultas,resultado);
				(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se consulta recorriendo secuencialmente el archivo." );
			} else
				(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se consulta utilizando el indice secundario." );		
		}
		else{
			(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se consulta por campo clave accediendo a indice primario." );
			TipoDato* clave = consultas[0]->get_valor();
			//obtengo a traves del indice el numero de bloque donde buscar el reg asociado a la clave
			int num_bloque = indice_primario->consultar(clave);
			if (num_bloque != Indice::VACIO) {
				(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se encontro el bloque en el indice primario. Se busca secuencial dentro del mismo." );
				BloqueSec bq_sec (Buffer::get_instance()->get_bloque(*this,num_bloque), this->get_registro_base());
				unsigned int pos = 0;
				bool encontrado = bq_sec.buscar_registro(clave, pos);
				if (encontrado) {
					TipoStruct* reg = bq_sec.get_registro(clave);
					resultado.push_back(reg);
				}		
				delete(bq_sec.get_bloque());
			}
		}
	}else
		throw ExcepArchCerrado("Error - El archivo : "+ this-> get_nombre() +" esta cerrado. ");
}

void SecuencialIndexado::actualizar(TipoStruct * reg) throw(ExcepArchCerrado,ExcepRegInexistente, ExcepBloqueTam){
	(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se actualiza un registro." );
	if (this-> fd != -1){
		(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se accede por campo clave mediante indice primario." );
		//accedo al bloque del registro por el indice primario, por campo 0 
		TipoDato* clave = &((*reg)[0]);
		int num_bloque = indice_primario->consultar(clave);
		if (num_bloque != Indice::VACIO){ //quiere decir que el registro asociado a la clave existe dentro de un bloque
			(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se encontro el bloque en el indice primario. Se busca secuencial dentro del mismo." );
			Bloque*	bloque_actual = NULL;
			TipoStruct* reg_b;
			try{
				bloque_actual = Buffer::get_instance()->get_bloque(*this,num_bloque);
				reg_b = (TipoStruct*) get_registro_base()->clonar();
				unsigned int pos, size;
				bool encontro;
				//lo busco dentro del bloque, se que es unico por que es consulta por campo 0			
				encontro = bloque_actual->buscar_por_clave_desde(sizeof(unsigned int), clave,reg_b, pos, size);
				if (encontro) {
					//saco el reg del bloque, si saque el primero, actualizo el ind primario
					sacar_reg_bloque(bloque_actual, reg, pos, size);
					//lo saco del indice secundario
					if (indice_secundario!= NULL)
						indice_secundario->quitar(reg_b);	
					//lo vuelvo a poner el en bloque modificado, vuelvo a actualizar el indice en caso
					//de ser necesario
					if ((bloque_actual->get_tope() <= get_primera_pos()) || (!poner_reg_en_bloque(bloque_actual, reg)))
						ingresar(reg);
					else {
						//lo pongo en el indice secundario
						if (indice_secundario!= NULL)
							indice_secundario->ingresar(reg);
					}	
				}	
				delete (reg_b);
				delete(bloque_actual);
				bloque_actual = NULL;
				if (!encontro)
					throw ExcepRegInexistente("Error - El registro a actualizar no existe en el archivo de datos. ");
			}catch (ExcepLeerBloque &e){
				if (bloque_actual != NULL) {
					delete (bloque_actual); 
					bloque_actual = NULL;
				}
				delete(reg_b);
				throw e;
			}
		}else
			throw ExcepRegInexistente("Error - El registro a actualizar no existe en el archivo de datos. ");	
			
	}else
		throw ExcepArchCerrado("Error - El archivo : "+ this-> get_nombre() +" esta cerrado. ");
}
 													
TiposArchivo SecuencialIndexado::get_tipo_archivo(){
	return SECUENCIAL_INDEXADO;
}

void SecuencialIndexado::eliminar() {
	(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Eliminando el archivo "+ this->get_nombre());
	//Elimino el archivo de espacios libres
	bloques_libres->eliminar();
	//Elimino el archivo de header
	std::string header = "./DATA/"+get_nombre()+".head";
	remove(header.c_str());
	//elimino indices
	indice_primario->eliminar();
	if (indice_secundario!=NULL)
		indice_secundario->eliminar();
	//Cierro el archivo
	this->cerrar();
	//Lo Elimino
	std::string mi_ruta = "./DATA/"+get_nombre();
	remove(mi_ruta.c_str()); 
}

unsigned int SecuencialIndexado::get_espacio_libre() throw(ExcepArchCerrado, ExcepLeerBloque){
	unsigned int resultado = 0;
	Bloque* bloque_actual;
	
	for(unsigned int i = 1; i < this->cant_bloques; i++ ){
		//obtengo el bloque nro i desde el buffer
		bloque_actual = Buffer::get_instance()->get_bloque(*this,i);
		//si el bloque no esta libre
		if (bloque_actual->get_tope() > this->get_primera_pos())
			//le pido al bloque el espacio libre
			resultado += bloque_actual->get_espacio_libre();
		else
			resultado += bloque_actual->get_size();
		//Borro el bloque que me devolvio el buffer
		delete (bloque_actual);
	}
	return resultado;
}

unsigned int SecuencialIndexado::get_esp_libre_indice()  throw(ExcepArchCerrado, ExcepLeerBloque){
	return indice_primario->get_espacio_libre();	
}
		 										
unsigned int SecuencialIndexado::get_cant_regs_indice() throw(ExcepArchCerrado){
	return indice_primario->get_cant_regs();	
}

long SecuencialIndexado::get_tam_arch_indice() throw(ExcepArchCerrado) {
	return indice_primario->get_tam();
}
 				
bool SecuencialIndexado::es_unico(TipoStruct * reg){
	//le mando el campo 0 que es el de la clave primaria
	TipoDato* clave = &(*reg)[0];
	bool resultado = true;
	unsigned int pos = 0;
	int n_bloque = indice_primario->consultar(clave);
	if( n_bloque != Indice::VACIO ) {
		BloqueSec bq (Buffer::get_instance()->get_bloque(*this, n_bloque), this->get_registro_base());
		resultado = !(bq.buscar_registro(clave, pos));
		delete (bq.get_bloque());
	}
	return resultado;
}

	
int SecuencialIndexado::sacar_reg_bloque(Bloque* bloque, TipoStruct* reg, unsigned int pos_reg, unsigned int tam_reg) {
	BloqueSec* bq_sec = new BloqueSec(bloque,this->get_registro_base());
	TipoDato* clave_bloque = bq_sec->obtener_primera_clave();
	TipoDato* clave = &((*reg)[0]);
	//Saco el reg del bloque
	bq_sec->quitar_registro(clave);
		
	if(bq_sec->vacio()){ //el bloque esta libre, actualizo archivo de bbll
		//actualizo indice, agrego el bloque como bb ll
		(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> El bloque quedo vacio, se agrega como libre, se saca del indice primario.");
		indice_primario->quitar(clave);
		bloques_libres->append(bloque->get_num_bloque());
	}else{
		//chequeo que cumpla con la densidad minima de llenado DENS_MIN
		double dens_min = (bloque->get_size()*DENS_MIN);
		if(bq_sec->get_tam_ocupado() < dens_min)
			manejar_underflow(bloque);
		(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se actualiza el indice primario");
		//actualizo indice, en caso de que haya habido alguna modificacion
		actualizar_primero(clave_bloque,bloque);
	}
	//lo devuelvo a disco despues de haber sacado el registro
	Buffer::get_instance()->guardar_bloque(*this,bloque);	
	
	delete clave_bloque;
	delete bq_sec;
	return 0;
}

void SecuencialIndexado::manejar_underflow(Bloque* bloque){
	(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se produjo un underflow ");
	//unsigned int num_bloque = bloque->get_num_bloque();
	bool unico_bloque = (this->get_cant_bloques() == 1); 
	if (!unico_bloque){ //me aseguro que por lo menor haya dos bloques
		//necesito unir al bloque actual con alguno de sus vecinos, en caso de no poder
		//fusionar, equilibrar ambos para que el bloque pasado por param salga del underflow
		Bloque*	bloque_hno = NULL;
		try{//siempre pido al siguiente, a la derecha
			TipoInt* sgte = ((IndiceArbol*) indice_primario)->get_siguiente();
			if (sgte != NULL){ //no es el ultimo
				bloque_hno = Buffer::get_instance()->get_bloque(*this,sgte->get_valor());
				delete (sgte);
				if (fusionar_bloques(bloque,bloque_hno)) {
					(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> Se fusiona con el siguiente bloque");
					//Si pudo fusionar, agrego como bloque libre el hermano
					bloques_libres->append(bloque_hno->get_num_bloque());
					//lo vacio
					bloque_hno->vaciar();
				} else	
					(Debug::get_instance() )->mostrar_mensaje("<SECUENCIAL INDEXADO> No puede fusionarse");	
				//guardo las modificaciones del bloque hno
				Buffer::get_instance()->guardar_bloque(*this,bloque_hno);
				//el bloque guarda sus modificaciones desde afuera
			}
			//si es el ultimo no hago nada, el underflow queda igual
			if(bloque_hno != NULL)	
				delete bloque_hno; 
		}catch (ExcepLeerBloque &e){
			if(bloque_hno != NULL)	
				delete bloque_hno; 
			throw e;
		}
	} //si es el unico el underflow queda igual
}

bool SecuencialIndexado::fusionar_bloques(Bloque* b_1,Bloque* b_2){
	BloqueSec* menores = new BloqueSec(b_1,this->get_registro_base());
	BloqueSec* mayores = new BloqueSec(b_2,this->get_registro_base());
	TipoDato* clave = mayores->obtener_primera_clave();
	bool resultado = menores->unir(mayores);
	//el de mayores vuelve vacio, lo libero desde afuera
	//quito la clave que le correspondia en el indice, del bloque hno que quedo vacio
	if (resultado)
		indice_primario->quitar(clave);
	delete clave;
	delete menores;
	delete mayores;
	return resultado;
}

void SecuencialIndexado::redistribuir(Bloque* actual, Bloque* hno){
	BloqueSec* menores = new BloqueSec(actual,this->get_registro_base());
	BloqueSec* mayores = new BloqueSec(hno,this->get_registro_base());
	TipoDato* clave = mayores->obtener_primera_clave();
	menores->equilibrar_bloques(mayores);
	//actualizo el indice, con respecto al bloque hno, que quedo modificado
	actualizar_primero(clave,mayores->get_bloque());	
	delete clave;
	delete menores;
	delete mayores;	
}

void SecuencialIndexado::dividir_bloque(Bloque* bloque_actual,Bloque* bloque_nuevo,TipoStruct* reg){
	BloqueSec* b_actual = new BloqueSec(bloque_actual,this->get_registro_base());
	TipoDato* clave = b_actual->obtener_primera_clave(); 
	//primer mitad en el actual, segunda en el nuevo
	//ingresa donde corresponda el reg
	BloqueSec* b_nuevo = new BloqueSec(bloque_nuevo,this->get_registro_base());
	b_actual->ingresar_con_split(b_nuevo,reg);	
	//chequeo que no se haya modificado la primer clave del bloque_actual, en caso de que me modifique el indice
	actualizar_primero(clave,bloque_actual);
	delete clave;
	delete b_actual;
	delete b_nuevo;	
}

bool SecuencialIndexado::poner_reg_en_bloque(Bloque* bloque, TipoStruct* reg){
	BloqueSec* b_actual = new BloqueSec(bloque,this->get_registro_base());
	TipoDato* clave_vieja = b_actual->obtener_primera_clave(); 
	//Meto el reg en el bloque
	bool retorno = b_actual->ingresar_registro(reg);
	if(!retorno) {
		delete (clave_vieja);
		delete (b_actual);
		return false;
	}
	//lo ingreso, chequeamos que no se haya modificado el primero, de haberse
	//modificado debo actualizar el indice 
	if (clave_vieja != NULL) {
		actualizar_primero(clave_vieja,bloque);
		delete (clave_vieja);
	} else {
		TipoDato* clave_nueva = b_actual->obtener_primera_clave();
		indice_primario->ingresar(clave_nueva, bloque->get_num_bloque());
		delete (clave_nueva);	
	}
	//lo devuelvo a disco despues de haber puesto el reg
	Buffer::get_instance()->guardar_bloque(*this,bloque);
	delete (b_actual);
	return retorno;
}

